//
//  GLBadgeLabel.m
//  KTools
//
//  Created by 121 on 2017/9/22.
//  Copyright © 2017年 杭州吉利控股信息中心. All rights reserved.
//

#import "GLBadgeLabel.h"
#import <objc/runtime.h>

#define GLBadgeCenterValueKey @"_value"
#define GLBadgeCenterObserverKey @"_observer"


@interface GLBadgeCenter ()
@property(nonatomic,strong)NSMutableDictionary* routers;
@end

@implementation GLBadgeCenter
+(instancetype)defaultCenter{
    static dispatch_once_t onceToken;
    static GLBadgeCenter* staticBadgeCenter;
    dispatch_once(&onceToken, ^{
        staticBadgeCenter = [[GLBadgeCenter alloc]init];
    });
    return staticBadgeCenter;
}
-(NSUInteger)valueForKeyPath:(NSString*)keyPath{
    NSMutableDictionary* subRouter = [self routerForKeyPath:keyPath];
    NSNumber* valueNumber = subRouter[GLBadgeCenterValueKey];
    NSUInteger value = 0;
    if (valueNumber) {
        value = [valueNumber integerValue];
    }
    return value;
}

-(void)setValue:(NSUInteger)value forKeyPath:(NSString*)keyPath{
    
    NSString* curPath = keyPath;
    NSMutableDictionary* subRouter = [self routerForKeyPath:curPath];
    [subRouter setValue:[NSNumber numberWithInteger:value] forKeyPath:GLBadgeCenterValueKey];
    [self notifierObserverByKeyPath:curPath];
    
    curPath = [self keyPathByDeleteLastPath:curPath];
    
    while (curPath) {
        subRouter = [self routerForKeyPath:curPath];
        
        NSInteger sum = [self sumOfSubRouters:subRouter];
        
        [subRouter setValue:[NSNumber numberWithInteger:sum] forKeyPath:GLBadgeCenterValueKey];
        
        [self notifierObserverByKeyPath:curPath];
        
        curPath = [self keyPathByDeleteLastPath:curPath];
    }

    
}

-(void)registerObserver:(GLBadgeLabel*)label forKeyPath:(NSString*)keyPath{

    NSMutableDictionary* subRouter = [self routerForKeyPath:keyPath];
    NSHashTable* observers = [self observerForRouter:subRouter];

    if (![observers containsObject:label]) {
        [observers addObject:label];
    }
    NSInteger value = [self valueForKeyPath:keyPath];
    [self configValue:[NSNumber numberWithInteger:value] forLabel:label];
}

-(void)removeObserver:(GLBadgeLabel*)label forKeyPath:(NSString*)keypath{
    NSMutableDictionary* subRouter = [self routerForKeyPath:keypath];
    NSHashTable* observers = [self observerForRouter:subRouter];

    if ([observers containsObject:label]) {
        [observers removeObject:label];
    }
}

-(NSMutableDictionary*)routerForKeyPath:(NSString*)keyPath{
    NSArray* keys = [self keysForKeyPath:keyPath];
    
    NSMutableDictionary* subRouter = self.routers;
    for (NSString* key in keys) {
        if (!subRouter[key]) {
            subRouter[key] = [NSMutableDictionary dictionaryWithCapacity:0];
        }
        subRouter = subRouter[key];
        
    }
    return subRouter;
}

-(NSArray*)keysForKeyPath:(NSString*)keyPath{
    NSArray* datas = [keyPath componentsSeparatedByString:@"."];
    return datas;
}

-(NSHashTable*)observerForRouter:(NSMutableDictionary*)router{
    if (!router[GLBadgeCenterObserverKey]) {
        router[GLBadgeCenterObserverKey] = [NSHashTable weakObjectsHashTable];
    }
    
    return router[GLBadgeCenterObserverKey];
}

-(void)notifierObserverByKeyPath:(NSString*)keyPath{
    NSMutableDictionary* subRouter = [self routerForKeyPath:keyPath];
    NSNumber* number = subRouter[GLBadgeCenterValueKey];
    
    NSHashTable* observers = subRouter[GLBadgeCenterObserverKey];
    
    NSEnumerator* enumerator = [observers objectEnumerator];
    GLBadgeLabel* label = nil;
    while (label = [enumerator nextObject])
    {
        [self configValue:number forLabel:label];
        
    }
    
}

-(void)configValue:(NSNumber*)number forLabel:(GLBadgeLabel*)label{
    
    
    if ([number integerValue] == 0) {
        label.text =  @"";
        label.hidden = YES;
    }else{
        label.text = [number stringValue];
        if (label.hidden) {
            label.hidden = NO;
        }
        
        [label sizeToFit];
    }
}

-(NSInteger)sumOfSubRouters:(NSMutableDictionary*)routers{
    NSInteger sum = 0;

    NSArray* keys = [routers allKeys];
    
    for (NSString* key in keys) {
        if ([key isEqualToString:GLBadgeCenterValueKey] || [key isEqualToString:GLBadgeCenterObserverKey]) {
            continue;
        }
        
        NSMutableDictionary* subDict = routers[key];
        NSNumber* number = subDict[GLBadgeCenterValueKey];
        if (number) {
            sum+=[number integerValue];
        }
    }
    return sum;
}

-(NSString*)keyPathByDeleteLastPath:(NSString*)keyPath{
    if ([keyPath rangeOfString:@"."].location == NSNotFound) {
        return nil;
    }
    NSRegularExpression* reg = [NSRegularExpression regularExpressionWithPattern:@"\\." options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray* results = [reg matchesInString:keyPath options:NSMatchingReportCompletion range:NSMakeRange(0, keyPath.length)];
    NSTextCheckingResult* result = [results lastObject];
    if (result) {
        return [keyPath substringToIndex:result.range.location];
    }
    return nil;
}

#pragma mark- setter and getter
-(NSMutableDictionary*)routers{
    if (!_routers) {
        _routers = [NSMutableDictionary dictionaryWithCapacity:0];
    }
    return _routers;
}

@end

CGFloat distanceBetweenPoints (CGPoint p1, CGPoint p2) {
    CGFloat deltaX = p2.x - p1.x;
    CGFloat deltaY = p2.y - p1.y;
    return sqrt(deltaX*deltaX + deltaY*deltaY);
};

@implementation GLBadgeLabel

@synthesize edgeInsets;

//下面三个方法用来初始化edgeInsets

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self configDefault];
    }
    return self;
}

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self configDefault];
}

-(void)dealloc{
    NSLog(@"");
}


- (id)initWithFrame:(CGRect)frame

{
    
    self = [super initWithFrame:frame];
    
    if (self) {
        
        [self configDefault];
    }
    
    return self;
    
}

-(void)setFrame:(CGRect)frame{
    if (frame.size.width < frame.size.height) {
        frame.size.width = frame.size.height;
    }
    [super setFrame:frame];
}

-(void)setFont:(UIFont *)font{
    [super setFont:font];
    self.edgeInsets = UIEdgeInsetsMake(2, font.pointSize/2.0, 2, font.pointSize/2.0);
}

-(void)configDefault{
    self.cornerRadius = -1;
    self.edgeInsets = UIEdgeInsetsMake(5, 6, 5, 6);
    self.backgroundColor = [UIColor redColor];
    self.textAlignment = NSTextAlignmentCenter;
    self.textColor = [UIColor whiteColor];
    self.clipsToBounds = YES;
    self.contentMode = UIViewContentModeCenter;
}

-(void)layoutSubviews{
    [super layoutSubviews];
    if (self.cornerRadius >= 0) {
        self.layer.cornerRadius = self.cornerRadius;
    }else{
        self.layer.cornerRadius = self.bounds.size.height/2.0;
    }
    
}

// 修改绘制文字的区域，edgeInsets增加bounds
-(CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
    /*
     调用父类该方法
     注意传入的UIEdgeInsetsInsetRect(bounds, self.edgeInsets),bounds是真正的绘图区域
     */
    CGRect rect = [super textRectForBounds:UIEdgeInsetsInsetRect(bounds,self.edgeInsets) limitedToNumberOfLines:numberOfLines];
    //根据edgeInsets，修改绘制文字的bounds
    rect.origin.x -= self.edgeInsets.left;
    rect.origin.y -= self.edgeInsets.top;
    rect.size.width += self.edgeInsets.left + self.edgeInsets.right;
    rect.size.height += self.edgeInsets.top + self.edgeInsets.bottom;
    return rect;
}


- (void)drawRect:(CGRect)rect

{
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
    
}


- (UIBezierPath* )bezierPathWithFromPoint:(CGPoint)fromPoint
                                  toPoint:(CGPoint)toPoint
                               fromRadius:(CGFloat)fromRadius
                                 toRadius:(CGFloat)toRadius scale:(CGFloat)scale{
    
    if (isnan(fromRadius) || isnan(toRadius)||isnan(fromRadius)||isnan(toRadius)) return nil;
    
    UIBezierPath* path = [[UIBezierPath alloc] init];
    CGFloat r = distanceBetweenPoints(fromPoint, toPoint);
    CGFloat offsetY = fabs(fromRadius-toRadius);
    if (r <= offsetY) {
        CGPoint center;
        CGFloat radius;
        if (fromRadius >= toRadius) {
            center = fromPoint;
            radius = fromRadius;
        } else {
            center = toPoint;
            radius = toRadius;
        }
        [path addArcWithCenter:center radius:radius startAngle:0 endAngle:2*M_PI clockwise:YES];
    } else {
        CGFloat originX = toPoint.x - fromPoint.x;
        CGFloat originY = toPoint.y - fromPoint.y;
        
        CGFloat fromOriginAngel = (originX >= 0)?atan(originY/originX):(atan(originY/originX)+M_PI);
        CGFloat fromOffsetAngel = (fromRadius >= toRadius)?acos(offsetY/r):(M_PI-acos(offsetY/r));
        CGFloat fromStartAngel = fromOriginAngel + fromOffsetAngel;
        CGFloat fromEndAngel = fromOriginAngel - fromOffsetAngel;
        
        CGPoint fromStartPoint = CGPointMake(fromPoint.x+cos(fromStartAngel)*fromRadius, fromPoint.y+sin(fromStartAngel)*fromRadius);
        
        CGFloat toOriginAngel = (originX < 0)?atan(originY/originX):(atan(originY/originX)+M_PI);
        CGFloat toOffsetAngel = (fromRadius < toRadius)?acos(offsetY/r):(M_PI-acos(offsetY/r));
        CGFloat toStartAngel = toOriginAngel + toOffsetAngel;
        CGFloat toEndAngel = toOriginAngel - toOffsetAngel;
        CGPoint toStartPoint = CGPointMake(toPoint.x+cos(toStartAngel)*toRadius, toPoint.y+sin(toStartAngel)*toRadius);
        
        CGPoint middlePoint = CGPointMake(fromPoint.x+(toPoint.x-fromPoint.x)/2, fromPoint.y+(toPoint.y-fromPoint.y)/2);
        CGFloat middleRadius = (fromRadius+toRadius)/2;
        
        CGPoint fromControlPoint = CGPointMake(middlePoint.x+sin(fromOriginAngel)*middleRadius*scale, middlePoint.y-cos(fromOriginAngel)*middleRadius*scale);
        
        CGPoint toControlPoint = CGPointMake(middlePoint.x+sin(toOriginAngel)*middleRadius*scale, middlePoint.y-cos(toOriginAngel)*middleRadius*scale);
        
        [path moveToPoint:fromStartPoint];
        
        //绘制from弧形
        [path addArcWithCenter:fromPoint radius:fromRadius startAngle:fromStartAngel endAngle:fromEndAngel clockwise:YES];
        
        //绘制from到to之间的贝塞尔曲线
        if (r > (fromRadius+toRadius)) {
            [path addQuadCurveToPoint:toStartPoint controlPoint:fromControlPoint];
        }
        
        //绘制to弧形
        [path addArcWithCenter:toPoint radius:toRadius startAngle:toStartAngel endAngle:toEndAngel clockwise:YES];
        
        //绘制to到from之间的贝塞尔曲线
        if (r > (fromRadius+toRadius)) {
            [path addQuadCurveToPoint:fromStartPoint controlPoint:toControlPoint];
        }
    }
    
    [path closePath];
    
    return path;
}

#pragma mark- setter and getter
-(void)setBindKeyPath:(NSString *)bindKeyPath{
    if (_bindKeyPath != bindKeyPath) {
        _bindKeyPath = bindKeyPath;
        [[GLBadgeCenter defaultCenter] registerObserver:self forKeyPath:bindKeyPath];
    }
}

@end

static char GLBadgeLabelLKey;

@implementation UIView (GLBadgeLabel)

-(GLBadgeLabel*)showBadge:(NSString*)badgeStr center:(CGPoint)center badgeColor:(UIColor*)color{

    if (!self.badgeLabel) {
        GLBadgeLabel* label = [[GLBadgeLabel alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
        
        label.font = [UIFont systemFontOfSize:12];
        self.badgeLabel = label;
    }
    
    if (badgeStr) {
        self.badgeLabel.hidden = NO;
        self.badgeLabel.text = badgeStr;
        
        self.badgeLabel.center = center;
        self.badgeLabel.backgroundColor = color;
        
        [self addSubview:self.badgeLabel];
        [self bringSubviewToFront:self.badgeLabel];
        [self.badgeLabel sizeToFit];
    }else{
        self.badgeLabel.text = nil;
        self.badgeLabel.hidden = YES;
        
    }

    return self.badgeLabel;
}

-(GLBadgeLabel*)showBadgeBindKeyPath:(NSString*)keyPath center:(CGPoint)center badgeColor:(UIColor*)color{

    if (!self.badgeLabel) {
        GLBadgeLabel* label = [[GLBadgeLabel alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
        
        label.font = [UIFont systemFontOfSize:12];
        self.badgeLabel = label;
    }
    self.badgeLabel.bindKeyPath = keyPath;
    
    self.badgeLabel.hidden = NO;
    
    self.badgeLabel.center = center;
    self.badgeLabel.backgroundColor = color;
    
    [self addSubview:self.badgeLabel];
    [self bringSubviewToFront:self.badgeLabel];
    [self.badgeLabel sizeToFit];
    
    return self.badgeLabel;
}


-(void)hideBadge{
    self.badgeLabel.hidden = YES;
}

#pragma mark- setter and getter
-(GLBadgeLabel*)badgeLabel{
    return  objc_getAssociatedObject(self, &GLBadgeLabelLKey);
}

-(void)setBadgeLabel:(GLBadgeLabel *)badgeLabel{
    GLBadgeLabel* label = [[GLBadgeLabel alloc]init];
    label.font = [UIFont systemFontOfSize:12];
    label.backgroundColor = [UIColor redColor];
    [self addSubview:label];
    objc_setAssociatedObject(self, &GLBadgeLabelLKey, label, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}




@end
